From 589379a6a4f6044b9bac82892861198ef3274a79 Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Mon, 30 Mar 2020 14:14:57 -0600 Subject: [PATCH] convert nmea format to Format class. (#524) --- CMakeLists.txt | 1 + GPSBabel.pro | 1 + Makefile.in | 42 +++---- gpssim.cc | 3 +- jtr.cc | 5 +- nmea.cc | 301 ++++++++++++++++++------------------------------- nmea.h | 190 +++++++++++++++++++++++++++++++ vecs.h | 4 +- 8 files changed, 329 insertions(+), 218 deletions(-) create mode 100644 nmea.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a3b851c00..054a25255 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,7 @@ set(HEADERS mapsend.h mynav.h navilink.h + nmea.h session.h shape.h shapelib/shapefil.h diff --git a/GPSBabel.pro b/GPSBabel.pro index 1a86a5825..5d28e4e67 100644 --- a/GPSBabel.pro +++ b/GPSBabel.pro @@ -136,6 +136,7 @@ HEADERS = \ mapsend.h \ mynav.h \ navilink.h \ + nmea.h \ session.h \ shape.h \ shapelib/shapefil.h \ diff --git a/Makefile.in b/Makefile.in index 3d6652321..c619865ed 100644 --- a/Makefile.in +++ b/Makefile.in @@ -512,7 +512,7 @@ filter_vecs.o: filter_vecs.cc defs.h config.h zlib/zlib.h zlib/zconf.h \ swapdata.h trackfilter.h transform.h validate.h gbversion.h vecs.h \ format.h geojson.h src/core/file.h ggv_bin.h gpx.h \ src/core/xmlstreamwriter.h src/core/xmltag.h legacyformat.h mynav.h \ - shape.h shapelib/shapefil.h xcsv.h garmin_fs.h jeeps/gps.h \ + nmea.h shape.h shapelib/shapefil.h xcsv.h garmin_fs.h jeeps/gps.h \ jeeps/../defs.h jeeps/gpsport.h jeeps/gpsdevice.h jeeps/gpssend.h \ jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h \ jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsmem.h \ @@ -535,8 +535,8 @@ garmin.o: garmin.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsmem.h \ jeeps/gpsrqst.h garmin_tables.h grtcirc.h jeeps/gpsserial.h vecs.h \ geojson.h src/core/file.h ggv_bin.h gpx.h src/core/xmlstreamwriter.h \ - src/core/xmltag.h legacyformat.h mynav.h shape.h shapelib/shapefil.h \ - xcsv.h src/core/textstream.h yahoo.h xmlgeneric.h + src/core/xmltag.h legacyformat.h mynav.h nmea.h shape.h \ + shapelib/shapefil.h xcsv.h src/core/textstream.h yahoo.h xmlgeneric.h garmin_device_xml.o: garmin_device_xml.cc defs.h config.h zlib/zlib.h \ zlib/zconf.h formspec.h inifile.h gbfile.h session.h \ src/core/datetime.h src/core/optional.h garmin_device_xml.h \ @@ -594,7 +594,7 @@ geo.o: geo.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ src/core/file.h geojson.o: geojson.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \ - geojson.h format.h src/core/file.h + geojson.h format.h src/core/file.h src/core/logging.h ggv_bin.o: ggv_bin.cc ggv_bin.h defs.h config.h zlib/zlib.h zlib/zconf.h \ formspec.h inifile.h gbfile.h session.h src/core/datetime.h \ src/core/optional.h format.h @@ -624,7 +624,8 @@ gopal.o: gopal.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ cet_util.h csv_util.h grtcirc.h jeeps/gpsmath.h jeeps/gpsport.h \ strptime.h gpssim.o: gpssim.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ - inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h + inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \ + nmea.h format.h gpsutil.o: gpsutil.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \ cet_util.h magellan.h @@ -799,7 +800,7 @@ jogmap.o: jogmap.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ garmin_tables.h jeeps/gpsmath.h jeeps/gpsport.h xmlgeneric.h jtr.o: jtr.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \ - csv_util.h + csv_util.h nmea.h format.h kml.o: kml.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \ grtcirc.h src/core/file.h src/core/logging.h \ @@ -817,12 +818,12 @@ magproto.o: magproto.cc defs.h config.h zlib/zlib.h zlib/zconf.h \ formspec.h inifile.h gbfile.h session.h src/core/datetime.h \ src/core/optional.h explorist_ini.h format.h gbser.h magellan.h vecs.h \ geojson.h src/core/file.h ggv_bin.h gpx.h src/core/xmlstreamwriter.h \ - src/core/xmltag.h legacyformat.h mynav.h shape.h shapelib/shapefil.h \ - xcsv.h garmin_fs.h jeeps/gps.h jeeps/../defs.h jeeps/gpsport.h \ - jeeps/gpsdevice.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \ - jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \ - jeeps/gpsmath.h jeeps/gpsmem.h jeeps/gpsrqst.h src/core/textstream.h \ - yahoo.h xmlgeneric.h + src/core/xmltag.h legacyformat.h mynav.h nmea.h shape.h \ + shapelib/shapefil.h xcsv.h garmin_fs.h jeeps/gps.h jeeps/../defs.h \ + jeeps/gpsport.h jeeps/gpsdevice.h jeeps/gpssend.h jeeps/gpsread.h \ + jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ + jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsmem.h jeeps/gpsrqst.h \ + src/core/textstream.h yahoo.h xmlgeneric.h main.o: main.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \ cet_util.h csv_util.h filter.h filter_vecs.h arcdist.h bend.h \ @@ -831,11 +832,12 @@ main.o: main.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ stackfilter.h swapdata.h trackfilter.h transform.h validate.h format.h \ src/core/file.h src/core/usasciicodec.h vecs.h geojson.h ggv_bin.h \ gpx.h src/core/xmlstreamwriter.h src/core/xmltag.h legacyformat.h \ - mynav.h shape.h shapelib/shapefil.h xcsv.h garmin_fs.h jeeps/gps.h \ - jeeps/../defs.h jeeps/gpsport.h jeeps/gpsdevice.h jeeps/gpssend.h \ - jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h \ - jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsmem.h \ - jeeps/gpsrqst.h src/core/textstream.h yahoo.h xmlgeneric.h + mynav.h nmea.h shape.h shapelib/shapefil.h xcsv.h garmin_fs.h \ + jeeps/gps.h jeeps/../defs.h jeeps/gpsport.h jeeps/gpsdevice.h \ + jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h \ + jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmath.h \ + jeeps/gpsmem.h jeeps/gpsrqst.h src/core/textstream.h yahoo.h \ + xmlgeneric.h mapasia.o: mapasia.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h mapbar_track.o: mapbar_track.cc defs.h config.h zlib/zlib.h zlib/zconf.h \ @@ -881,8 +883,8 @@ netstumbler.o: netstumbler.cc defs.h config.h zlib/zlib.h zlib/zconf.h \ src/core/optional.h cet_util.h csv_util.h nmea.o: nmea.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \ - cet_util.h gbser.h jeeps/gpsmath.h jeeps/gpsport.h src/core/logging.h \ - strptime.h + nmea.h format.h cet_util.h gbser.h jeeps/gpsmath.h jeeps/gpsport.h \ + src/core/logging.h strptime.h nmn4.o: nmn4.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \ cet_util.h csv_util.h @@ -1048,7 +1050,7 @@ vecs.o: vecs.cc defs.h config.h zlib/zlib.h zlib/zconf.h formspec.h \ inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \ vecs.h format.h geojson.h src/core/file.h ggv_bin.h gpx.h \ src/core/xmlstreamwriter.h src/core/xmltag.h legacyformat.h mynav.h \ - shape.h shapelib/shapefil.h xcsv.h garmin_fs.h jeeps/gps.h \ + nmea.h shape.h shapelib/shapefil.h xcsv.h garmin_fs.h jeeps/gps.h \ jeeps/../defs.h jeeps/gpsport.h jeeps/gpsdevice.h jeeps/gpssend.h \ jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h \ jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsmem.h \ diff --git a/gpssim.cc b/gpssim.cc index 01e33175a..36efa4f17 100644 --- a/gpssim.cc +++ b/gpssim.cc @@ -24,6 +24,7 @@ #include #include #include +#include "nmea.h" #define MYNAME "gpssim" @@ -91,7 +92,7 @@ gpssim_wr_deinit() static void gpssim_write_sentence(const char* const s) { - gbfprintf(fout, "$%s*%02X\r\n", s, nmea_cksum(s)); + gbfprintf(fout, "$%s*%02X\r\n", s, NmeaFormat::nmea_cksum(s)); } static void diff --git a/jtr.cc b/jtr.cc index 2a863e816..e96f9f32b 100644 --- a/jtr.cc +++ b/jtr.cc @@ -26,6 +26,7 @@ #include #include #include +#include "nmea.h" #define MYNAME "jtr" @@ -302,11 +303,11 @@ jtr_trkpt_disp_cb(const Waypoint* wpt) scourse, CSTR(sdate)); - xasprintf(&tmp, "%s*%02X", str, nmea_cksum(str)); + xasprintf(&tmp, "%s*%02X", str, NmeaFormat::nmea_cksum(str)); xfree(str); str = tmp; - xasprintf(&tmp, "%s,,,E,,E*%02X\r", str, nmea_cksum(str)); + xasprintf(&tmp, "%s,,,E,,E*%02X\r", str, NmeaFormat::nmea_cksum(str)); xfree(str); str = tmp; diff --git a/nmea.cc b/nmea.cc index 82287e4a7..65cc8ca18 100644 --- a/nmea.cc +++ b/nmea.cc @@ -20,27 +20,29 @@ */ -#include // for isprint -#include // for fabs, lround -#include // for snprintf, sscanf, NULL, fprintf, fputc, stderr -#include // for atoi, atof -#include // for strncmp, memset, strlen, strchr, strstr, strrchr -#include // for gmtime -#include // for operator!=, reverse_iterator - -#include // for QByteArray -#include // for QChar, operator==, operator!= -#include // for QCharRef -#include // for QDateTime -#include // for QList -#include // for QString, QString::KeepEmptyParts -#include // for QStringList -#include // for QThread -#include // for QTime -#include // for QVector -#include // for qPrintable +#include // for isprint +#include // for fabs, lround +#include // for snprintf, sscanf, NULL, fprintf, fputc, stderr +#include // for atoi, atof, strtod +#include // for strncmp, memset, strlen, strchr, strstr, strrchr +#include // for time_t, gmtime +#include // for operator!=, reverse_iterator + +#include // for QByteArray +#include // for QChar, operator==, operator!= +#include // for QCharRef +#include // for QDateTime +#include // for QDebug +#include // for QList +#include // for QString, QString::KeepEmptyParts +#include // for QStringList +#include // for hex +#include // for QThread +#include // for QTime +#include // for qPrintable, foreach #include "defs.h" +#include "nmea.h" #include "cet_util.h" // for cet_convert_init #include "gbfile.h" // for gbfprintf, gbfflush, gbfclose, gbfopen, gbfgetstr, gbfile #include "gbser.h" // for gbser_set_speed, gbser_flush, gbser_read_line, gbser_deinit, gbser_init, gbser_write @@ -156,88 +158,14 @@ time I have seen this is when the recording stops suddenly, where the last sentence is truncated - and missing part of the line, including the checksum. */ -enum preferred_posn_type { - gp_unknown = 0, - gpgga, - gplgll, - gprmc -}; - -static enum { - rm_unknown = 0, - rm_serial, - rm_file -} read_mode; - -static gbfile* file_in, *file_out; -static route_head* trk_head; -static short_handle mkshort_handle; -static preferred_posn_type posn_type; -static struct tm tm; -static Waypoint* curr_waypt; -static Waypoint* last_waypt; -static void* gbser_handle; -static QString posn_fname; -static QList pcmpt_head; - -static int without_date; /* number of created trackpoints without a valid date */ -static struct tm opt_tm; /* converted "date" parameter */ - #define MYNAME "nmea" - -static char* opt_gprmc; -static char* opt_gpgga; -static char* opt_gpvtg; -static char* opt_gpgsa; -static char* snlenopt; -static char* optdate; -static char* getposnarg; -static char* opt_sleep; -static char* opt_baud; -static char* opt_append; -static char* opt_gisteq; -static char* opt_ignorefix; - -static long sleepus; -static int getposn; -static int append_output; -static bool amod_waypoint; - -static time_t last_time; -static double last_read_time; /* Last timestamp of GGA or PRMC */ -static int datum; -static int had_checksum; - -static Waypoint* nmea_rd_posn(posn_status*); -static void nmea_rd_posn_init(const QString& fname); - -static int wpt_not_added_yet; - -static QVector nmea_args = { - {"snlen", &snlenopt, "Max length of waypoint name to write", "6", ARGTYPE_INT, "1", "64", nullptr }, - {"gprmc", &opt_gprmc, "Read/write GPRMC sentences", "1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, - {"gpgga", &opt_gpgga, "Read/write GPGGA sentences", "1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, - {"gpvtg", &opt_gpvtg, "Read/write GPVTG sentences", "1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, - {"gpgsa", &opt_gpgsa, "Read/write GPGSA sentences", "1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, - {"date", &optdate, "Complete date-free tracks with given date (YYYYMMDD).", nullptr, ARGTYPE_INT, ARG_NOMINMAX , nullptr }, - { - "get_posn", &getposnarg, "Return current position as a waypoint", - nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr - }, - {"pause", &opt_sleep, "Decimal seconds to pause between groups of strings", nullptr, ARGTYPE_INT, ARG_NOMINMAX , nullptr}, - {"append_positioning", &opt_append, "Append realtime positioning data to the output file instead of truncating", "0", ARGTYPE_BOOL, ARG_NOMINMAX , nullptr}, - {"baud", &opt_baud, "Speed in bits per second of serial port (baud=4800)", nullptr, ARGTYPE_INT, ARG_NOMINMAX, nullptr }, - {"gisteq", &opt_gisteq, "Write tracks for Gisteq Phototracker", "0", ARGTYPE_BOOL, ARG_NOMINMAX , nullptr}, - {"ignore_fix", &opt_ignorefix, "Accept position fixes in gpgga marked invalid", "0", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr}, -}; - #define CHECK_BOOL(a) if ((a) && (*(a) == '0')) (a) = NULL /* * Slightly different than the Magellan checksum fn. */ int -nmea_cksum(const char* const buf) +NmeaFormat::nmea_cksum(const char* const buf) { int x = 0 ; @@ -247,8 +175,8 @@ nmea_cksum(const char* const buf) return x; } -static Waypoint* -nmea_new_wpt() +Waypoint* +NmeaFormat::nmea_new_wpt() { auto* wpt = new Waypoint(); // Set extra data to something other than nullptr to indicate to @@ -258,8 +186,8 @@ nmea_new_wpt() return wpt; } -static void -nmea_add_wpt(Waypoint* wpt, route_head* trk) +void +NmeaFormat::nmea_add_wpt(Waypoint* wpt, route_head* trk) const { // Reset extra data. // This also indicates to nmea_release_wpt that ownership has been @@ -280,8 +208,8 @@ nmea_add_wpt(Waypoint* wpt, route_head* trk) } } -static void -nmea_release_wpt(Waypoint* wpt) +void +NmeaFormat::nmea_release_wpt(Waypoint* wpt) { if (wpt && (wpt->extra_data != nullptr)) { // Ownership of this waypoint hasn't been transferred to a global @@ -290,8 +218,8 @@ nmea_release_wpt(Waypoint* wpt) } } -static void -nmea_rd_init(const QString& fname) +void +NmeaFormat::rd_init(const QString& fname) { curr_waypt = nullptr; last_waypt = nullptr; @@ -316,8 +244,8 @@ nmea_rd_init(const QString& fname) */ if (getposn) { posn_status st; - nmea_rd_posn_init(fname); - Waypoint* wpt = nmea_rd_posn(&st); + rd_position_init(fname); + Waypoint* wpt = rd_position(&st); if (!wpt) { return; } @@ -330,8 +258,8 @@ nmea_rd_init(const QString& fname) file_in = gbfopen(fname, "rb", MYNAME); } -static void -nmea_rd_deinit() +void +NmeaFormat::rd_deinit() { switch (read_mode) { case rm_serial: @@ -350,8 +278,8 @@ nmea_rd_deinit() } -static void -nmea_wr_init(const QString& portname) +void +NmeaFormat::wr_init(const QString& fname) { CHECK_BOOL(opt_gprmc); CHECK_BOOL(opt_gpgga); @@ -361,7 +289,7 @@ nmea_wr_init(const QString& portname) append_output = strtod(opt_append, nullptr); - file_out = gbfopen(portname, append_output ? "a+" : "w+", MYNAME); + file_out = gbfopen(fname, append_output ? "a+" : "w+", MYNAME); sleepus = -1; if (opt_sleep) { @@ -382,15 +310,15 @@ nmea_wr_init(const QString& portname) } } -static void -nmea_wr_deinit() +void +NmeaFormat::wr_deinit() { gbfclose(file_out); mkshort_del_handle(&mkshort_handle); } -static void -nmea_set_waypoint_time(Waypoint* wpt, struct tm* time, double fsec) +void +NmeaFormat::nmea_set_waypoint_time(Waypoint* wpt, struct tm* time, double fsec) { if (time->tm_year == 0) { wpt->SetCreationTime(((((time_t)time->tm_hour * 60) + time->tm_min) * 60) + time->tm_sec, lround(1000.0 * fsec)); @@ -407,8 +335,8 @@ nmea_set_waypoint_time(Waypoint* wpt, struct tm* time, double fsec) } } -static void -gpgll_parse(char* ibuf) +void +NmeaFormat::gpgll_parse(char* ibuf) { if (trk_head == nullptr) { trk_head = new route_head; @@ -462,8 +390,8 @@ gpgll_parse(char* ibuf) curr_waypt = waypt; } -static void -gpgga_parse(char* ibuf) +void +NmeaFormat::gpgga_parse(char* ibuf) { if (trk_head == nullptr) { trk_head = new route_head; @@ -558,8 +486,8 @@ gpgga_parse(char* ibuf) curr_waypt = waypt; } -static void -gprmc_parse(char* ibuf) +void +NmeaFormat::gprmc_parse(char* ibuf) { if (trk_head == nullptr) { trk_head = new route_head; @@ -654,8 +582,8 @@ gprmc_parse(char* ibuf) } } -static void -gpwpl_parse(char* ibuf) +void +NmeaFormat::gpwpl_parse(char* ibuf) { // The last field isn't actually separated by a field separator and // is a string, so we brutally whack the checksum (trailing *NN). @@ -690,8 +618,8 @@ gpwpl_parse(char* ibuf) nmea_add_wpt(waypt, nullptr); } -static void -gpzda_parse(char* ibuf) +void +NmeaFormat::gpzda_parse(char* ibuf) { double hms; int dd, mm, yy, lclhrs, lclmins; @@ -716,8 +644,8 @@ gpzda_parse(char* ibuf) // here. // The numbering as per http://aprs.gids.nl/nmea/#gsa was the reference as // the field numbers conveniently match our index. -static void -gpgsa_parse(char* ibuf) +void +NmeaFormat::gpgsa_parse(char* ibuf) const { int prn[12] = {0}; memset(prn,0xff,sizeof(prn)); @@ -767,8 +695,8 @@ gpgsa_parse(char* ibuf) } -static void -gpvtg_parse(char* ibuf) +void +NmeaFormat::gpvtg_parse(char* ibuf) const { QStringList fields = QString(ibuf).split(",", QString::KeepEmptyParts); double course = 0; @@ -793,16 +721,15 @@ gpvtg_parse(char* ibuf) * AVMAP EKP-IV Tracks - a proprietary (and very weird) extended NMEA. * https://sourceforge.net/tracker/?func=detail&atid=489478&aid=1640814&group_id=58972 */ -static -double pcmpt_deg(int d) +double NmeaFormat::pcmpt_deg(int d) { int deg = d / 100000; double minutes = (((d / 100000.0) - deg) * 100) / 60.0; return (double) deg + minutes; } -static void -pcmpt_parse(char* ibuf) +void +NmeaFormat::pcmpt_parse(char* ibuf) { int i, j1, j2, j3, j4, j5, j6; int lat, lon; @@ -877,8 +804,8 @@ pcmpt_parse(char* ibuf) } } -static void -nmea_fix_timestamps(route_head* track) +void +NmeaFormat::nmea_fix_timestamps(route_head* track) { if ((trk_head == nullptr) || (without_date == 0)) { return; @@ -927,8 +854,8 @@ nmea_fix_timestamps(route_head* track) } } -static int -notalkerid_strmatch(const char * s1, const char *sentenceFormatterMnemonicCode) +int +NmeaFormat::notalkerid_strmatch(const char * s1, const char *sentenceFormatterMnemonicCode) { /* * compare leading start of parametric sentence character ('$'), sentence address field, and trailing comma @@ -941,8 +868,8 @@ notalkerid_strmatch(const char * s1, const char *sentenceFormatterMnemonicCode) return strncmp(s1,"$",1) || strncmp(s1+3,sentenceFormatterMnemonicCode,3) || strncmp(s1+6,",",1); } -static void -nmea_parse_one_line(char* ibuf) +void +NmeaFormat::nmea_parse_one_line(char* ibuf) { char* tbuf = lrtrim(ibuf); @@ -1029,8 +956,8 @@ nmea_parse_one_line(char* ibuf) } } -static void -nmea_read() +void +NmeaFormat::read() { char* ibuf; double lt = -1; @@ -1108,7 +1035,7 @@ nmea_read() } void -nmea_rd_posn_init(const QString& fname) +NmeaFormat::rd_position_init(const QString& fname) { if ((gbser_handle = gbser_init(qPrintable(fname))) != nullptr) { read_mode = rm_serial; @@ -1127,8 +1054,8 @@ nmea_rd_posn_init(const QString& fname) posn_fname = fname; } -static void -safe_print(int cnt, const char* b) +void +NmeaFormat::safe_print(int cnt, const char* b) { for (int i = 0; i < cnt; i++) { char c = isprint(b[i]) ? b[i] : '.'; @@ -1136,10 +1063,7 @@ safe_print(int cnt, const char* b) } } -static void reset_sirf_to_nmea(int br); - -static -int hunt_sirf() +int NmeaFormat::hunt_sirf() { /* Try to place the common BR's first to speed searching */ static int br[] = {38400, 9600, 57600, 115200, 19200, 4800, -1}; @@ -1179,8 +1103,8 @@ int hunt_sirf() return 0; } -static Waypoint* -nmea_rd_posn(posn_status*) +Waypoint* +NmeaFormat::rd_position(posn_status* /*unused*/) { char ibuf[1024]; static double lt = -1; @@ -1231,8 +1155,14 @@ nmea_rd_posn(posn_status*) return nullptr; } -static void -nmea_wayptpr(const Waypoint* wpt) +void +NmeaFormat::rd_position_deinit() +{ + rd_deinit(); +} + +void +NmeaFormat::nmea_wayptpr(const Waypoint* wpt) const { char obuf[200]; QString s; @@ -1256,14 +1186,15 @@ nmea_wayptpr(const Waypoint* wpt) QThread::usleep(sleepus); } } -static void -nmea_track_init(const route_head*) + +void +NmeaFormat::nmea_track_init(const route_head* /*unused*/) { last_time = -1; } -static void -nmea_trackpt_pr(const Waypoint* wpt) +void +NmeaFormat::nmea_trackpt_pr(const Waypoint* wpt) { char obuf[200]; char fix='0'; @@ -1381,55 +1312,40 @@ nmea_trackpt_pr(const Waypoint* wpt) gbfflush(file_out); } -static void -nmea_write() +void +NmeaFormat::write() { - waypt_disp_all(nmea_wayptpr); - track_disp_all(nmea_track_init, nullptr, nmea_trackpt_pr); + auto nmea_wayptpr_lambda = [this](const Waypoint* waypointp)->void { + nmea_wayptpr(waypointp); + }; + waypt_disp_all(nmea_wayptpr_lambda); + auto nmea_track_init_lambda = [this](const route_head* rte)->void { + nmea_track_init(rte); + }; + auto nmea_trackpt_pr_lambda = [this](const Waypoint* waypointp)->void { + nmea_trackpt_pr(waypointp); + }; + track_disp_all(nmea_track_init_lambda, nullptr, nmea_trackpt_pr_lambda); } -static void -nmea_wr_posn_init(const QString& fname) +void +NmeaFormat::wr_position_init(const QString& fname) { - nmea_wr_init(fname); + wr_init(fname); } -static void -nmea_wr_posn(Waypoint* wpt) +void +NmeaFormat::wr_position(Waypoint* wpt) { nmea_trackpt_pr(wpt); } -static void -nmea_wr_posn_deinit() +void +NmeaFormat::wr_position_deinit() { // nmea_wr_deinit(); } - -ff_vecs_t nmea_vecs = { - ff_type_file, - { - (ff_cap)(ff_cap_read | ff_cap_write), - (ff_cap)(ff_cap_read | ff_cap_write), - ff_cap_none - }, - nmea_rd_init, - nmea_wr_init, - nmea_rd_deinit, - nmea_wr_deinit, - nmea_read, - nmea_write, - nullptr, - &nmea_args, - CET_CHARSET_ASCII, 0, /* CET-REVIEW */ - { - nmea_rd_posn_init, nmea_rd_posn, nmea_rd_deinit, - nmea_wr_posn_init, nmea_wr_posn, nmea_wr_posn_deinit - }, - nullptr -}; - /* * If we later decide to implement a "real" Sirf module, this code should * go there. For now, we try a kind of heavy handed thing - if we don't @@ -1437,8 +1353,8 @@ ff_vecs_t nmea_vecs = { * a SiRF Star device and send it the "speak NMEA, please" command. */ -static void -sirf_write(unsigned char* buf) +void +NmeaFormat::sirf_write(unsigned char* buf) const { int chksum = 0; int len = buf[2] << 8 | buf[3]; @@ -1454,8 +1370,7 @@ sirf_write(unsigned char* buf) gbser_write(gbser_handle, buf, len + 8); /* 4 at front, 4 at back */ } -static -void reset_sirf_to_nmea(int br) +void NmeaFormat::reset_sirf_to_nmea(int br) { static unsigned char pkt[] = {0xa0, 0xa2, 0x00, 0x18, 0x81, 0x02, diff --git a/nmea.h b/nmea.h new file mode 100644 index 000000000..f09b988fa --- /dev/null +++ b/nmea.h @@ -0,0 +1,190 @@ +/* + Read files containing selected NMEA 0183 sentences. + Based on information by Eino Uikkanenj + + Copyright (C) 2004-2015 Robert Lipe, robertlipe+source@gpsbabel.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ +#ifndef NMEA_H_INCLUDED_ +#define NMEA_H_INCLUDED_ + +#include // for gmtime + +#include // for QList +#include // for QString, QString::KeepEmptyParts +#include // for QVector + +#include "defs.h" +#include "format.h" +#include "gbfile.h" // for gbfprintf, gbfflush, gbfclose, gbfopen, gbfgetstr, gbfile + + +class NmeaFormat : public Format +{ +public: + /* Member Functions */ + + QVector* get_args() override + { + return &nmea_args; + } + + ff_type get_type() const override + { + return ff_type_file; + } + + QVector get_cap() const override + { + return { + (ff_cap)(ff_cap_read | ff_cap_write), + (ff_cap)(ff_cap_read | ff_cap_write), + ff_cap_none + }; + } + + QString get_encode() const override + { + return CET_CHARSET_ASCII; + } + + int get_fixed_encode() const override + { + return 0; + } + + void rd_init(const QString& fname) override; + void read() override; + void rd_deinit() override; + void wr_init(const QString& fname) override; + void write() override; + void wr_deinit() override; + void rd_position_init(const QString& fname) override; + Waypoint* rd_position(posn_status* status) override; + void rd_position_deinit() override; + void wr_position_init(const QString& fname) override; + void wr_position(Waypoint* wpt) override; + void wr_position_deinit() override; + + static int nmea_cksum(const char* const buf); + +private: + /* Types */ + + enum preferred_posn_type { + gp_unknown = 0, + gpgga, + gplgll, + gprmc + }; + + enum { + rm_unknown = 0, + rm_serial, + rm_file + } read_mode; + + /* Member Functions */ + + Waypoint* nmea_new_wpt(); + void nmea_add_wpt(Waypoint* wpt, route_head* trk) const; + static void nmea_release_wpt(Waypoint* wpt); + void nmea_set_waypoint_time(Waypoint* wpt, tm* time, double fsec); + void gpgll_parse(char* ibuf); + void gpgga_parse(char* ibuf); + void gprmc_parse(char* ibuf); + void gpwpl_parse(char* ibuf); + void gpzda_parse(char* ibuf); + void gpgsa_parse(char* ibuf) const; + void gpvtg_parse(char* ibuf) const; + static double pcmpt_deg(int d); + void pcmpt_parse(char* ibuf); + void nmea_fix_timestamps(route_head* track); + static int notalkerid_strmatch(const char* s1, const char* sentenceFormatterMnemonicCode); + void nmea_parse_one_line(char* ibuf); + static void safe_print(int cnt, const char* b); + int hunt_sirf(); + void nmea_wayptpr(const Waypoint* wpt) const; + void nmea_track_init(const route_head* unused); + void nmea_trackpt_pr(const Waypoint* wpt); + void sirf_write(unsigned char* buf) const; + void reset_sirf_to_nmea(int br); + + /* Data Members */ + + gbfile* file_in, *file_out; + route_head* trk_head; + short_handle mkshort_handle; + preferred_posn_type posn_type; + struct tm tm; + Waypoint* curr_waypt; + Waypoint* last_waypt; + void* gbser_handle; + QString posn_fname; + QList pcmpt_head; + + int without_date; /* number of created trackpoints without a valid date */ + struct tm opt_tm; /* converted "date" parameter */ + + char* opt_gprmc; + char* opt_gpgga; + char* opt_gpvtg; + char* opt_gpgsa; + char* snlenopt; + char* optdate; + char* getposnarg; + char* opt_sleep; + char* opt_baud; + char* opt_append; + char* opt_gisteq; + char* opt_ignorefix; + + long sleepus; + int getposn; + int append_output; + bool amod_waypoint; + + time_t last_time; + double last_read_time; /* Last timestamp of GGA or PRMC */ + int datum; + int had_checksum; + + Waypoint* nmea_rd_posn(posn_status*); + void nmea_rd_posn_init(const QString& fname); + + int wpt_not_added_yet; + + QVector nmea_args = { + {"snlen", &snlenopt, "Max length of waypoint name to write", "6", ARGTYPE_INT, "1", "64", nullptr }, + {"gprmc", &opt_gprmc, "Read/write GPRMC sentences", "1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, + {"gpgga", &opt_gpgga, "Read/write GPGGA sentences", "1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, + {"gpvtg", &opt_gpvtg, "Read/write GPVTG sentences", "1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, + {"gpgsa", &opt_gpgsa, "Read/write GPGSA sentences", "1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, + {"date", &optdate, "Complete date-free tracks with given date (YYYYMMDD).", nullptr, ARGTYPE_INT, ARG_NOMINMAX, nullptr }, + { + "get_posn", &getposnarg, "Return current position as a waypoint", + nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr + }, + {"pause", &opt_sleep, "Decimal seconds to pause between groups of strings", nullptr, ARGTYPE_INT, ARG_NOMINMAX, nullptr}, + {"append_positioning", &opt_append, "Append realtime positioning data to the output file instead of truncating", "0", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr}, + {"baud", &opt_baud, "Speed in bits per second of serial port (baud=4800)", nullptr, ARGTYPE_INT, ARG_NOMINMAX, nullptr }, + {"gisteq", &opt_gisteq, "Write tracks for Gisteq Phototracker", "0", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr}, + {"ignore_fix", &opt_ignorefix, "Accept position fixes in gpgga marked invalid", "0", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr}, + }; + +}; +#endif // NMEA_H_INCLUDED_ diff --git a/vecs.h b/vecs.h index c3952440b..9cbadfd43 100644 --- a/vecs.h +++ b/vecs.h @@ -34,6 +34,7 @@ #include "gpx.h" #include "legacyformat.h" #include "mynav.h" +#include "nmea.h" #include "shape.h" #include "xcsv.h" #include "yahoo.h" @@ -47,7 +48,6 @@ extern ff_vecs_t garmin_vecs; extern ff_vecs_t gdb_vecs; extern ff_vecs_t mapsend_vecs; extern ff_vecs_t mps_vecs; -extern ff_vecs_t nmea_vecs; extern ff_vecs_t ozi_vecs; extern ff_vecs_t pcx_vecs; extern ff_vecs_t kml_vecs; @@ -276,7 +276,7 @@ private: LegacyFormat gdb_fmt {gdb_vecs}; LegacyFormat mapsend_fmt {mapsend_vecs}; LegacyFormat mps_fmt {mps_vecs}; - LegacyFormat nmea_fmt {nmea_vecs}; + NmeaFormat nmea_fmt; LegacyFormat ozi_fmt {ozi_vecs}; LegacyFormat pcx_fmt {pcx_vecs}; LegacyFormat kml_fmt {kml_vecs}; -- 2.30.2